package com.hengpeng.itfin.domain.draw.alipay;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.hengpeng.common.exception.ServiceResult;
import com.hengpeng.itfin.domain.draw.AbstractDrawProcessor;
import com.hengpeng.itfin.domain.draw.common.Constants;
import com.hengpeng.itfin.domain.draw.common.FileCSVHelper;
import com.hengpeng.itfin.domain.draw.common.FileZipHelper;
import com.hengpeng.itfin.domain.draw.common.PayUtil;
import com.hengpeng.itfin.service.ServiceFactory;
import com.hengpeng.itfin.tools.Payment;
import com.hengpeng.itfinbase.persist.DrawFile;
import com.hengpeng.itfinbase.persist.DrawFile.DealState;
import com.hengpeng.itfinbase.persist.Drawing;
import com.hengpeng.itfinbase.persist.Drawing.DrawingState;
import com.hengpeng.itfinbase.persist.PaymentProvider;

/**
 * <pre>
 *  输入类型说明
 * </pre>
 * @author shanguogang
 * @version 1.0, 2015-8-12
 */
public class AlipayDrawProcessor extends AbstractDrawProcessor
{
	private static final String ALIPAY_TRANS_FLAG = "2";

	private static final Log logger = LogFactory.getLog(AlipayDrawProcessor.class);

	protected String download_service = "bptb_result_file";

	protected String biz_type = "d_sale";

	protected String bussiness_type = "T0";

	protected int connectTimeout = 10000;

	protected String file_digest_type = "MD5";

	protected String input_charset = "gbk";

	protected String upload_service = "bptb_pay_file";

	private ServiceFactory serviceFactory;

	protected String sign_type = "MD5";

	public static Map<String, String> resultMsgMap = new HashMap<String, String>();
	static
	{
		logger.info("初始化上传结果消息");
		resultMsgMap.put("ILLEGAL_SERVICE", "service参数不正确");
		resultMsgMap.put("HAS_NO_PRIVILEGE", "没有访问权限");
		resultMsgMap.put("ILLEGAL_SIGN", "签名不正确");
		resultMsgMap.put("ILLEGAL_DIGEST", "文件摘要不正确");
		resultMsgMap.put("上传成功", "上传成功");
		resultMsgMap.put("上传失败 : 文件名格式不正确", "文件名格式不正确");
		resultMsgMap.put("上传失败：重复上传相同的文件", "重复上传相同的文件");
		resultMsgMap.put("上传失败：超过当天上传次数", "超过当天上传次数");
	}

	public AlipayDrawProcessor(ApplicationContext context, PaymentProvider provider)
	{
		super(context, provider);
		serviceFactory = context.getBean(ServiceFactory.class);
	}

	private void analyzeFileContent(String providerId, String fileContent, String csvname)
	{
		String[] lines = fileContent.split("\r\n");
		if (lines != null)
		{
			logger.info("开始处理" + csvname + "]中的数据 共 " + lines.length + " 行.从第三行开始处理");

			for (int i = 3; i < lines.length; i++)
			{
				String[] items = lines[i].split(Constants.ALIPAY_SEPARATOR);
				if (items != null && items.length > 0)
				{
					String drawingTransNo = items[0];
					String drawingTransState = items[9];
					DrawingState state = null;
					String msg = null;
					if (drawingTransState.equalsIgnoreCase("S"))
					{// 提款成功
						state = DrawingState.SUCCESS;
						msg = DrawingState.SUCCESS.getText();
					}
					else if (drawingTransState.equalsIgnoreCase("F"))
					{// 提款失败
						logger.error("[商户流水号:" + drawingTransNo + "],[支付宝的提现流水号:" + items[10] + "],[备注:" + items[12]
								+ "]");
						state = DrawingState.FAILED;
						msg = items[12];
					}
					else
					{
						state = DrawingState.DEALING;
						msg = items[12];
					}
					// 处理提款结果(成功:改状态;　失败:退款并改状态)
					serviceFactory.getDrawingService().dealResult(providerId, drawingTransNo, state, msg);
				}
			}
		}
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public DrawFile createBatchDrawFile(PaymentProvider provider, List<Drawing> drawList)
	{
		DrawFile drawFile = null;
		logger.info("来自支付提供商:[" + provider.getName() + "]的提款记录数有:" + drawList.size() + "条");
		StringBuffer contentBuf = new StringBuffer();
		StringBuffer recordBuf = new StringBuffer();
		recordBuf.append(Constants.ALIPAY_UPLOAD_TABLE_TITLE_SEQ).append(Constants.ALIPAY_SEPARATOR);
		recordBuf.append(Constants.ALIPAY_UPLOAD_TABLE_TITLE_USERNAME).append(Constants.ALIPAY_SEPARATOR);
		recordBuf.append(Constants.ALIPAY_UPLOAD_TABLE_TITLE_BANKACOUNT).append(Constants.ALIPAY_SEPARATOR);
		recordBuf.append(Constants.ALIPAY_UPLOAD_TABLE_TITLE_BANKNAME).append(Constants.ALIPAY_SEPARATOR);
		recordBuf.append(Constants.ALIPAY_UPLOAD_TABLE_TITLE_PROVINCE).append(Constants.ALIPAY_SEPARATOR);
		recordBuf.append(Constants.ALIPAY_UPLOAD_TABLE_TITLE_CITY).append(Constants.ALIPAY_SEPARATOR);
		recordBuf.append(Constants.ALIPAY_UPLOAD_TABLE_TITLE_BRANCHNAME).append(Constants.ALIPAY_SEPARATOR);
		recordBuf.append(Constants.ALIPAY_UPLOAD_TABLE_TITLE_MONEY).append(Constants.ALIPAY_SEPARATOR);
		recordBuf.append(Constants.ALIPAY_UPLOAD_TABLE_TITLE_FLAG).append(Constants.ALIPAY_SEPARATOR);
		recordBuf.append(Constants.ALIPAY_UPLOAD_TABLE_TITLE_NOTE).append("\r\n");
		// 生成提款文件
		String sysDatetime = PayUtil.getCurrDate();
		int totalRecord = drawList.size();
		float totalMoney = 0;
		for (Drawing bean : drawList)
		{
			serviceFactory.getDaoFactory().getCommonDao().lockObject(Drawing.class, bean.getId());
			recordBuf.append(bean.getOrdId()).append(Constants.ALIPAY_SEPARATOR);
			recordBuf.append(bean.getRealName()).append(Constants.ALIPAY_SEPARATOR);
			recordBuf.append(bean.getBankCardNo()).append(Constants.ALIPAY_SEPARATOR);
			recordBuf.append(bean.getBankName()).append(Constants.ALIPAY_SEPARATOR);
			recordBuf.append(bean.getProvince()).append(Constants.ALIPAY_SEPARATOR);
			recordBuf.append(bean.getCity()).append(Constants.ALIPAY_SEPARATOR);
			DecimalFormat df = new DecimalFormat("#0.00");
			Double d = Double.valueOf(bean.getMoney());
			double betmoney = new Double(df.format(d / 100));
			double money = PayUtil.formatDouble(PayUtil.recoup(betmoney));
			recordBuf.append(PayUtil.recoupBankAddress(money, bean.getSubbranch())).append(Constants.ALIPAY_SEPARATOR);
			// 扣除提现手续费
			recordBuf.append(money).append(Constants.ALIPAY_SEPARATOR);
			totalMoney += money;

			recordBuf.append(ALIPAY_TRANS_FLAG).append(Constants.ALIPAY_SEPARATOR);
			recordBuf.append("mark" + bean.getUserName());
			recordBuf.append("\r\n");
		}
		// 文件概要部分
		contentBuf.append(Constants.ALIPAY_UPLOAD_MAIN_TITLE_DATE).append(Constants.ALIPAY_SEPARATOR);
		contentBuf.append(Constants.ALIPAY_UPLOAD_MAIN_TITLE_TOTALMONEY).append(Constants.ALIPAY_SEPARATOR);
		contentBuf.append(Constants.ALIPAY_UPLOAD_MAIN_TITLE_TOTALRECORD).append(Constants.ALIPAY_SEPARATOR);
		contentBuf.append(Constants.ALIPAY_UPLOAD_MAIN_TITLE_ALIPAYACOUNT);
		contentBuf.append("\r\n");

		contentBuf.append(sysDatetime.substring(0, 8)).append(Constants.ALIPAY_SEPARATOR);
		contentBuf.append(totalMoney).append(Constants.ALIPAY_SEPARATOR);
		contentBuf.append(totalRecord).append(Constants.ALIPAY_SEPARATOR);
		contentBuf.append(provider.getAccountId());
		contentBuf.append("\r\n");
		contentBuf.append(recordBuf);

		String csvfile = sysDatetime + Constants.POSTFIX_CSV;
		// 查检路径,没有则自动创建
		String path = null;
		try
		{
			path = FileCSVHelper.checkPath(provider.getPayFilePath() + File.separator + provider.getId()
					+ File.separator + "upload" + File.separator);
			// 生成CSV文件
			if (FileCSVHelper.generateCSVFile(path + csvfile, contentBuf.toString()))
			{
				drawFile = new DrawFile();
				drawFile.setCreateTime(new Date());
				drawFile.setUpload_fileName(csvfile);
				drawFile.setUpload_path(path);
				drawFile.setProviderId(provider.getId());
				drawFile.setState(DealState.UPLOAD_WAIT);
			}
		}
		catch (Exception e)
		{
			logger.error("创 建上传文件 [" + csvfile + "] 异常.", e);
		}

		return drawFile;
	}

	/**
	 * 支付宝的提现 扣除手续费处理 (0-5万元（不包含5万元）1元每笔； 5万元以上5元每笔)
	 * @param oldMoney 　原始提款金额　单位＂元＂
	 * @return　扣除手续费后的提款金额 单位＂元＂
	 */
	public static double recoup(double oldMoney, String drawtype)
	{
		double newMoney = 0;
		if (oldMoney > 0)
		{
			if ("T0".equalsIgnoreCase(drawtype))
			{
				if (oldMoney < 20000)
				{
					newMoney = oldMoney - 2;
				}
				else if ((oldMoney >= 20000) && (oldMoney < 50000))
				{
					newMoney = oldMoney - 4;
				}
				else if ((oldMoney >= 50000) && (oldMoney < 100000))
				{
					newMoney = oldMoney - 6;
				}
				else if ((oldMoney >= 100000) && (oldMoney < 200000))
				{
					newMoney = oldMoney - 10;
				}
				else if ((oldMoney >= 20000) && (oldMoney < 500000))
				{
					newMoney = oldMoney - 20;
				}
				else if ((oldMoney >= 500000) && (oldMoney < 1000000))
				{
					newMoney = oldMoney - 30;
				}
				else
				{
					newMoney = oldMoney - 50;
				}
			}
			else
			{
				if (oldMoney < 20000)
				{
					newMoney = oldMoney - 1;
				}
				else if ((oldMoney >= 20000) && (oldMoney < 50000))
				{
					newMoney = oldMoney - 3;
				}
				else if ((oldMoney >= 50000) && (oldMoney < 1000000))
				{
					newMoney = oldMoney - 5;
				}
				else
				{
					newMoney = oldMoney - 20;
				}
			}
		}
		else
		{
			newMoney = 0;
		}
		return newMoney;
	}

	@Override
	public void downBatchDrawFileResult(PaymentProvider provider, DrawFile file)
	{
		String zipfile = Constants.ALIPAY_PAY_RESULT_ZIP_PRE_FIX
				+ file.getUpload_fileName().substring(0, file.getUpload_fileName().indexOf(".")) + "_"
				+ Payment.getCurrDate() + Constants.POSTFIX_ZIP;
		logger.info("通过文件 [" + file.getUpload_fileName() + "],开始从支付宝下载对应结果文件  [" + zipfile + "]");
		String itemUrl = Payment.CreateUrlForDown(download_service, provider.getMerchantId(), biz_type,
				file.getUpload_fileName(), sign_type, provider.getCheckKey(), input_charset);
		PostMethod mPost = new PostMethod(provider.getPayUrl());
		// 不带附件的传参方式
		NameValuePair[] pairs = new NameValuePair[7];
		pairs[0] = new NameValuePair("_input_charset", input_charset);
		pairs[1] = new NameValuePair("partner", provider.getMerchantId());
		pairs[2] = new NameValuePair("service", download_service);
		pairs[3] = new NameValuePair("sign", itemUrl);
		pairs[4] = new NameValuePair("sign_type", sign_type);
		pairs[5] = new NameValuePair("file_name", file.getUpload_fileName());
		pairs[6] = new NameValuePair("biz_type", biz_type);
		mPost.setRequestBody(pairs);

		HttpClient client = new HttpClient();
		client.getHttpConnectionManager().getParams().setConnectionTimeout(connectTimeout);
		try
		{
			int status = client.executeMethod(mPost);
			if (status == HttpStatus.SC_OK)
			{ // 连接成功
				String respMsg = mPost.getResponseBodyAsString();

				// 返回结果信息
				logger.info("开始接收文件...");
				byte b[] = mPost.getResponseBody();
				System.out.println("数据流长度:" + b.length);
				if (b.length > 500)
				{
					String downloadPath = FileCSVHelper.checkPath(provider.getPayFilePath() + "/" + provider.getId()
							+ "/download/");
					FileOutputStream out = new FileOutputStream(downloadPath + zipfile);
					out.write(b, 0, b.length);
					out.close();
					logger.info("文件下载成功");
					file.setDownTime(new Date());
					file.setState(DealState.DOWN_SUCCESS);
					file.setDown_path(downloadPath);
					file.setDown_fileName(zipfile);
					serviceFactory.getPersistService().update(file);
				}
				else
				{
					logger.error("文件下载失败!错误信息:" + respMsg);
				}
			}
			else
			{
				logger.error("通信失败!");
			}
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}
		finally
		{
			mPost.releaseConnection();
		}
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void parseBatchDrawResultFile(PaymentProvider provider, DrawFile file)
	{
		serviceFactory.getDaoFactory().getCommonDao().lockObject(DrawFile.class, file.getId());
		logger.info("开始解析并处理提款结果文件:[" + file.getDown_fileName() + "]");
		try
		{
			logger.info("开始分析 [" + file.getDown_fileName() + "]");
			Map<String, byte[]> fileMap = FileZipHelper.unZip(file.getDown_path() + file.getDown_fileName(), "gbk");
			if (fileMap == null)
			{
				logger.error("分析提款结果文件出错!请人工检查提现结果文件！");
				return;
			}
			logger.info("分析 [" + file.getDown_fileName() + "] 完成.");

			Set<String> keySet = fileMap.keySet();
			String fileNames[] = new String[keySet.size()];
			keySet.toArray(fileNames);
			for (int i = 0; i < fileNames.length; i++)
			{
				if (fileNames[i].indexOf(Constants.POSTFIX_CSV) > 0
						&& fileNames[i].indexOf(Constants.ALIPAY__RESULT_CSV) == -1)
				{// deal
					// with

					logger.info("开始分析[" + file.getDown_fileName() + "]中的子文件[" + fileNames[i] + "] ");
					byte[] b = fileMap.get(fileNames[i]);
					String fileContent = new String(b, 0, b.length);
					analyzeFileContent(file.getProviderId(), fileContent, fileNames[i]);
					logger.info("分析 [" + fileNames[i] + "]文件并完成付费结果数据处理 ");
				}
			}
			file.setState(DealState.OVER);
			serviceFactory.getPersistService().update(file);
		}
		catch (Exception e)
		{
			logger.error("解析并处理提款结果文件时出现异常");
			e.printStackTrace();
		}
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public DrawFile uploadBatchDrawFile(PaymentProvider provider, DrawFile file)
	{
		PostMethod mPost = new PostMethod(provider.getPayUrl());
		FileInputStream fileInputStream = null;
		try
		{
			String fullFileName = file.getUpload_path() + file.getUpload_fileName();
			File targetFile = new File(file.getUpload_path(), file.getUpload_fileName());
			fileInputStream = new FileInputStream(targetFile);
			String digest_bptb_pay_file = DigestUtils.md5Hex(IOUtils.toByteArray(fileInputStream));

			String ItemUrl = Payment.CreateUrlForUpload(upload_service, provider.getMerchantId(), biz_type,
					file_digest_type, sign_type, provider.getCheckKey(), input_charset, digest_bptb_pay_file,
					bussiness_type);
			logger.info("签名sign =" + ItemUrl);
			// ----带附件的传参方式 设参开始----
			Part sp1 = new StringPart("_input_charset", input_charset);
			Part sp2 = new StringPart("partner", provider.getMerchantId());
			Part sp3 = new StringPart("service", upload_service);
			Part sp4 = new StringPart("sign", ItemUrl);
			Part sp5 = new StringPart("sign_type", sign_type);
			Part sp6 = new StringPart("digest_bptb_pay_file", digest_bptb_pay_file.toString());
			Part sp7 = new StringPart("file_digest_type", file_digest_type);
			Part sp8 = new StringPart("biz_type", biz_type);

			Part sp9 = new StringPart("bussiness_type", bussiness_type);
			Part fp = new FilePart("bptb_pay_file", targetFile);

			MultipartRequestEntity mrp = new MultipartRequestEntity(new Part[] { sp1, sp2, sp3, sp4, sp5, sp6, sp7,
					sp8, sp9, fp }, mPost.getParams());
			mPost.setRequestEntity(mrp);

			// ----完成设参-----
			HttpClient client = new HttpClient();
			client.getHttpConnectionManager().getParams().setConnectionTimeout(connectTimeout);
			int status = client.executeMethod(mPost);
			if (status == HttpStatus.SC_OK)
			{
				// 上传成功
				String respMsg = mPost.getResponseBodyAsString();
				if (respMsg != null && respMsg.indexOf(Constants.ALIPAY_UPLOAD_R_SUCCESS) > -1)
				{
					logger.info("上传成功!文件名：[" + fullFileName + "]");
					// 上传成功后修改文件状态
					file.setUploadTime(new Date());
					file.setState(DealState.UPLOAD_SUCCESS);
				}
				else
				{
					logger.error("上传失败!文件名：[" + fullFileName + "]");
					file.setUploadTime(new Date());
					file.setState(DealState.UPLOAD_WAIT);
					logger.error("返回结果:" + respMsg + ",结果说明:" + resultMsgMap.get(respMsg));
				}
				return file;
			}
			else
			{
				logger.error("上传失败,通信异常");
				return null;
			}
		}
		catch (Throwable e)
		{
			logger.error("上传文件异常", e);
			return null;
		}
		finally
		{
			mPost.releaseConnection();
			if (fileInputStream != null)
			{
				try
				{
					fileInputStream.close();
				}
				catch (IOException e)
				{
					logger.error("关闭连接异常", e);
				}
			}
		}
	}

	@Override
	public ServiceResult<Drawing> singleDrawRequest(Drawing drawing)
	{
		return null;
	}

	@Override
	public Drawing singleDrawQueryRequest(Drawing drawing)
	{
		return null;
	}

}
